"""
文件名: category.py
描述: 频道分类数据模型定义

本模块包含以下主要功能：
1. Category数据库模型 - SQLAlchemy ORM模型
2. CategoryCreate - 分类创建时的数据验证模型
3. CategoryUpdate - 分类更新时的数据验证模型
4. CategoryInDB - 数据库查询返回的分类模型
5. UserChannel - 用户频道关联模型

依赖模块:
   - sqlalchemy: ORM框架和数据库操作
   - pydantic: 数据验证和序列化
   - datetime: 时间处理
   - typing: 类型注解

使用示例:
   >>> from src.models.category import Category, CategoryCreate
   >>> category_data = CategoryCreate(
   ...     name="科技",
   ...     icon="🔬",
   ...     color="#3b82f6"
   ... )
   >>> category = Category(**category_data.dict())

注意事项:
   - 分类名称在用户范围内唯一
   - 支持自定义图标和颜色
   - 频道可以属于多个分类
   - 删除采用软删除方式

作者: AI助手
创建日期: 2024-06-27
最后修改: 2024-06-27
版本: 1.0.0
"""

from datetime import datetime
from typing import Optional, List

from sqlalchemy import Column, String, DateTime, Boolean, Text, Integer, ForeignKey, Table
from sqlalchemy.dialects.postgresql import UUID, JSONB
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship
import uuid

from pydantic import BaseModel, Field, validator

from src.core.database import Base


# 频道分类关联表（多对多关系）
channel_category_association = Table(
    'channel_categories',
    Base.metadata,
    Column('channel_id', UUID(as_uuid=True), ForeignKey('channels.id'), primary_key=True),
    Column('category_id', UUID(as_uuid=True), ForeignKey('categories.id'), primary_key=True),
    Column('created_at', DateTime(timezone=True), server_default=func.now()),
)


class Category(Base):
    """
    频道分类数据库模型
    
    用户可以创建自定义分类来组织订阅频道
    """
    __tablename__ = "categories"
    
    # 主键和基本信息
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False, index=True, comment="所属用户ID")
    name = Column(String(100), nullable=False, comment="分类名称")
    description = Column(Text, nullable=True, comment="分类描述")
    
    # 视觉配置
    icon = Column(String(10), nullable=True, comment="分类图标（emoji或图标名）")
    color = Column(String(20), nullable=True, comment="分类颜色（十六进制）")
    
    # 排序和状态
    sort_order = Column(Integer, default=0, nullable=False, comment="排序顺序")
    is_default = Column(Boolean, default=False, nullable=False, comment="是否为默认分类")
    is_active = Column(Boolean, default=True, nullable=False, comment="分类是否激活")
    
    # 统计信息
    channel_count = Column(Integer, default=0, nullable=False, comment="包含频道数量")
    
    # 配置信息（JSON格式）
    settings = Column(JSONB, nullable=True, comment="分类设置")
    
    # 时间戳
    created_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        nullable=False,
        comment="创建时间"
    )
    updated_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        onupdate=func.now(),
        nullable=False,
        comment="更新时间"
    )
    deleted_at = Column(DateTime(timezone=True), nullable=True, comment="删除时间（软删除）")
    
    # 关系映射
    # user = relationship("User", back_populates="categories")
    # channels = relationship("Channel", secondary=channel_category_association, back_populates="categories")
    
    def __repr__(self) -> str:
        return f"<Category(id={self.id}, name={self.name}, user_id={self.user_id})>"
    
    @property
    def is_deleted(self) -> bool:
        """检查分类是否被删除"""
        return self.deleted_at is not None
    
    @property
    def display_name(self) -> str:
        """获取显示名称（包含图标）"""
        if self.icon:
            return f"{self.icon} {self.name}"
        return self.name


class UserChannel(Base):
    """
    用户频道关联模型
    
    记录用户订阅的频道及其分类关联
    """
    __tablename__ = "user_channels"
    
    # 主键和关联
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4, index=True)
    user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'), nullable=False, index=True, comment="用户ID")
    channel_id = Column(UUID(as_uuid=True), ForeignKey('channels.id'), nullable=False, index=True, comment="频道ID")
    
    # 用户自定义信息
    custom_name = Column(String(255), nullable=True, comment="用户自定义频道名称")
    notes = Column(Text, nullable=True, comment="用户备注")
    
    # 状态信息
    is_subscribed = Column(Boolean, default=True, nullable=False, comment="是否订阅")
    is_notification_enabled = Column(Boolean, default=True, nullable=False, comment="是否启用通知")
    subscription_date = Column(DateTime(timezone=True), nullable=True, comment="订阅日期")
    
    # 用户设置（JSON格式）
    preferences = Column(JSONB, nullable=True, comment="用户偏好设置")
    
    # 时间戳
    created_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        nullable=False,
        comment="创建时间"
    )
    updated_at = Column(
        DateTime(timezone=True), 
        server_default=func.now(), 
        onupdate=func.now(),
        nullable=False,
        comment="更新时间"
    )
    
    # 关系映射
    # user = relationship("User", back_populates="user_channels")
    # channel = relationship("Channel", back_populates="user_channels")
    
    def __repr__(self) -> str:
        return f"<UserChannel(id={self.id}, user_id={self.user_id}, channel_id={self.channel_id})>"


class CategoryBase(BaseModel):
    """分类基础数据模型"""
    name: str = Field(..., min_length=1, max_length=100, description="分类名称")
    description: Optional[str] = Field(None, max_length=500, description="分类描述")
    icon: Optional[str] = Field(None, max_length=10, description="分类图标")
    color: Optional[str] = Field(None, max_length=20, description="分类颜色")
    sort_order: Optional[int] = Field(0, ge=0, description="排序顺序")
    
    class Config:
        from_attributes = True


class CategoryCreate(CategoryBase):
    """分类创建数据模型"""
    user_id: uuid.UUID = Field(..., description="所属用户ID")
    is_default: Optional[bool] = Field(False, description="是否为默认分类")
    settings: Optional[dict] = Field(None, description="分类设置")
    
    @validator("name")
    def validate_name(cls, v):
        """验证分类名称"""
        if not v or not v.strip():
            raise ValueError("分类名称不能为空")
        return v.strip()
    
    @validator("color")
    def validate_color(cls, v):
        """验证颜色格式"""
        if v and not v.startswith("#"):
            raise ValueError("颜色必须是十六进制格式（以#开头）")
        if v and len(v) not in [4, 7]:  # #RGB 或 #RRGGBB
            raise ValueError("颜色格式无效")
        return v


class CategoryUpdate(BaseModel):
    """分类更新数据模型"""
    name: Optional[str] = Field(None, min_length=1, max_length=100, description="分类名称")
    description: Optional[str] = Field(None, max_length=500, description="分类描述")
    icon: Optional[str] = Field(None, max_length=10, description="分类图标")
    color: Optional[str] = Field(None, max_length=20, description="分类颜色")
    sort_order: Optional[int] = Field(None, ge=0, description="排序顺序")
    is_active: Optional[bool] = Field(None, description="分类是否激活")
    settings: Optional[dict] = Field(None, description="分类设置")
    
    @validator("name")
    def validate_name(cls, v):
        """验证分类名称"""
        if v is not None and (not v or not v.strip()):
            raise ValueError("分类名称不能为空")
        return v.strip() if v else v
    
    @validator("color")
    def validate_color(cls, v):
        """验证颜色格式"""
        if v and not v.startswith("#"):
            raise ValueError("颜色必须是十六进制格式（以#开头）")
        if v and len(v) not in [4, 7]:  # #RGB 或 #RRGGBB
            raise ValueError("颜色格式无效")
        return v
    
    class Config:
        from_attributes = True


class CategoryInDB(CategoryBase):
    """数据库查询返回的分类模型"""
    id: uuid.UUID = Field(..., description="分类ID")
    user_id: uuid.UUID = Field(..., description="所属用户ID")
    is_default: bool = Field(..., description="是否为默认分类")
    is_active: bool = Field(..., description="分类是否激活")
    channel_count: int = Field(..., description="包含频道数量")
    settings: Optional[dict] = Field(None, description="分类设置")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")
    
    @property
    def display_name(self) -> str:
        """获取显示名称（包含图标）"""
        if self.icon:
            return f"{self.icon} {self.name}"
        return self.name


class CategoryWithChannels(CategoryInDB):
    """包含频道信息的分类模型"""
    channels: List[dict] = Field(default_factory=list, description="关联的频道列表")
    
    class Config:
        from_attributes = True


class CategorySummary(BaseModel):
    """分类摘要信息模型（列表页面使用）"""
    id: uuid.UUID = Field(..., description="分类ID")
    name: str = Field(..., description="分类名称")
    icon: Optional[str] = Field(None, description="分类图标")
    color: Optional[str] = Field(None, description="分类颜色")
    channel_count: int = Field(..., description="包含频道数量")
    is_default: bool = Field(..., description="是否为默认分类")
    sort_order: int = Field(..., description="排序顺序")
    
    @property
    def display_name(self) -> str:
        """获取显示名称（包含图标）"""
        if self.icon:
            return f"{self.icon} {self.name}"
        return self.name
    
    class Config:
        from_attributes = True


class UserChannelBase(BaseModel):
    """用户频道关联基础模型"""
    custom_name: Optional[str] = Field(None, max_length=255, description="用户自定义频道名称")
    notes: Optional[str] = Field(None, max_length=1000, description="用户备注")
    is_notification_enabled: Optional[bool] = Field(True, description="是否启用通知")
    
    class Config:
        from_attributes = True


class UserChannelCreate(UserChannelBase):
    """用户频道关联创建模型"""
    user_id: uuid.UUID = Field(..., description="用户ID")
    channel_id: uuid.UUID = Field(..., description="频道ID")
    subscription_date: Optional[datetime] = Field(None, description="订阅日期")
    preferences: Optional[dict] = Field(None, description="用户偏好设置")


class UserChannelUpdate(UserChannelBase):
    """用户频道关联更新模型"""
    is_subscribed: Optional[bool] = Field(None, description="是否订阅")
    preferences: Optional[dict] = Field(None, description="用户偏好设置")
    
    class Config:
        from_attributes = True


class UserChannelInDB(UserChannelBase):
    """数据库查询返回的用户频道关联模型"""
    id: uuid.UUID = Field(..., description="关联ID")
    user_id: uuid.UUID = Field(..., description="用户ID")
    channel_id: uuid.UUID = Field(..., description="频道ID")
    is_subscribed: bool = Field(..., description="是否订阅")
    subscription_date: Optional[datetime] = Field(None, description="订阅日期")
    preferences: Optional[dict] = Field(None, description="用户偏好设置")
    created_at: datetime = Field(..., description="创建时间")
    updated_at: datetime = Field(..., description="更新时间")


# 预设分类配置
DEFAULT_CATEGORIES = [
    {"name": "科技", "icon": "🔬", "color": "#3b82f6", "sort_order": 1},
    {"name": "娱乐", "icon": "🎬", "color": "#ef4444", "sort_order": 2},
    {"name": "体育", "icon": "⚽", "color": "#22c55e", "sort_order": 3},
    {"name": "教育", "icon": "📚", "color": "#8b5cf6", "sort_order": 4},
    {"name": "生活", "icon": "🌟", "color": "#f59e0b", "sort_order": 5},
    {"name": "游戏", "icon": "🎮", "color": "#06b6d4", "sort_order": 6},
    {"name": "新闻", "icon": "📰", "color": "#6b7280", "sort_order": 7},
    {"name": "音乐", "icon": "🎵", "color": "#ec4899", "sort_order": 8},
    {"name": "未分类", "icon": "📂", "color": "#94a3b8", "sort_order": 99},
]